import 'dart:async';

import 'package:bluetooth_protocols_parser_plugin/src/lorin/cmd/v12s_cmd.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/integrated/v12s_integrated_product_info.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/integrated/v12s_integrated_realtime_info.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/lorin_protocol.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/realtime/battery/v12s_realtime_battery_info.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/realtime/error/v12s_realtime_error.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/realtime/info/v12s_realtime_info.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/realtime/info/v12s_reatime_all_info.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/realtime/status/v12s_realtime_status.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/settings/v12s_settings.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/statistics/v12s_statistics_once_data.dart';
import 'package:bluetooth_protocols_parser_plugin/src/lorin/statistics/v12s_statistics_total_data.dart';
import 'package:bluetooth_protocols_plugin/library.dart';

import '../../enum/target_device_type.dart';
import '../lorin_helper.dart';
import '../../response/lorin_response_data.dart';

class V12sProtocol extends LorinProtocol<
    V12sRealtimeInfo,
    V12sRealtimeStatus,
    V12sRealtimeError,
    V12sRealtimeAllInfo,
    V12sRealtimeBatteryInfo,
    V12sStatisticsOnceData,
    V12sStatisticsTotalData,
    V12sSettings,
    V12sIntegratedProductInfo,
    V12sIntegratedRealtimeInfo,
    LorinResponseData> {
  @override
  LorinPrivateIntructionMessage get privateInstrMessage =>
      _V12sPrivateIntructionMessage();

  //
  // 蓝牙主动响应监听
  StreamSubscription? _bluetoothNotifyStreamSubscription;

  @override
  Future<V12sRealtimeInfo> getRealtimeInfo() {
    return sendRequest(privateInstrMessage.getRealtimeInfoIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para == null) {
        throw Exception('Get V12sRealtimeInfo failed');
      }
      return V12sRealtimeInfo.fromBytes(msg.data!.para!);
    });
  }

  @override
  Future<V12sRealtimeStatus> getRealtimeStatus() {
    return sendRequest(privateInstrMessage.getRealtimeStatusIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return V12sRealtimeStatus.fromBytes(msg.data!.para!);
      }
      throw Exception('Get V12sRealtimeStatus failed');
    });
  }

  @override
  Future<V12sRealtimeError> getRealtimeError() {
    return sendRequest(privateInstrMessage.getRealtimeErrorIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return V12sRealtimeError.fromBytes(msg.data!.para!);
      }
      throw Exception('Get V12sRealtimeError failed');
    });
  }

  @override
  Future<V12sRealtimeAllInfo> getRealtimeAll() {
    return sendRequest(privateInstrMessage.getRealtimeAllIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return V12sRealtimeAllInfo.fromBytes(msg.data!.para!);
      }
      throw Exception('Get V12sRealtimeAllInfo failed');
    });
  }

  @override
  Future<V12sSettings> getSettingsAll() {
    return sendRequest(privateInstrMessage.getSettingsAllIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return V12sSettings.fromBytes(msg.data!.para!);
      }
      throw Exception('Get V12sSettings failed');
    });
  }

  @override
  Future<V12sStatisticsOnceData> getStatisticOnce(
      {int? startIndex, int? count}) {
    return sendRequest(privateInstrMessage
            .getStatisticOnceIntrMsg(startNum: startIndex, count: count)
            .toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return V12sStatisticsOnceData.fromBytes(msg.data!.para!);
      }
      throw Exception('Get V12sStatisticsOnceData failed');
    });
  }

  @override
  Future<V12sStatisticsTotalData> getStatisticsTotal() {
    return sendRequest(
            privateInstrMessage.getStatisticsTotalIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return V12sStatisticsTotalData.fromBytes(msg.data!.para!);
      }
      throw Exception('Get V12sStatisticsTotalData failed');
    });
  }

  @override
  Future<V12sRealtimeBatteryInfo> getRealtimeBatteryInfo() {
    return sendRequest(
            privateInstrMessage.getRealtimeBatteryInfoIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return V12sRealtimeBatteryInfo.fromBytes(msg.data!.para!);
      }
      throw Exception('Get V12sRealtimeBatteryInfo failed');
    });
  }

  @override
  Future<V12sIntegratedProductInfo> getIntegratedProductInfo() {
    return sendRequest(
            privateInstrMessage.getIntegratedProductInfoIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return V12sIntegratedProductInfo.fromBytes(msg.data!.para!);
      }
      throw Exception('Get V12sIntegratedProductInfo failed');
    });
  }

  @override
  Future<V12sIntegratedRealtimeInfo> getIntegratedRealtimeInfoAll() {
    return sendRequest(
            privateInstrMessage.getIntegratedRealtimeInfoAllIntrMsg().toBytes())
        .then((rspMsg) {
      LorinMessage msg = LorinMessage.fromList(rspMsg);
      if (msg.data?.para != null) {
        return V12sIntegratedRealtimeInfo.fromBytes(msg.data!.para!);
      }
      throw Exception('Get V12sIntegratedRealtimeInfo failed');
    });
  }

  @override
  void cancelBluetoothNotifyStream() {
    _bluetoothNotifyStreamSubscription?.cancel();
    _bluetoothNotifyStreamSubscription = null;
  }

  @override
  void listenBluetoothNotifyStream(
      {Function(LorinResponseData p1)? callbackNfcCardPairSuccess,
      Function(V12sRealtimeInfo p1)? callbackRealtimeInfo,
      Function(V12sIntegratedRealtimeInfo p1)? callbackRealtimeAllInfo}) {
    _bluetoothNotifyStreamSubscription?.cancel();
    _bluetoothNotifyStreamSubscription = responseNotifyStream?.listen((data) {
      LorinMessage? lorinMessages = LorinHelper.bytesToLorinMessage(data);
      if (lorinMessages != null &&
          lorinMessages.data != null &&
          callbackRealtimeAllInfo != null) {
        callbackRealtimeAllInfo(V12sIntegratedRealtimeInfo.fromBytes(
            lorinMessages.data!.toBytes()));
      }
    });
  }
}

class _V12sPrivateIntructionMessage extends LorinPrivateIntructionMessage {
  @override
  get privateRequestBody => _V12sPrivateRequestBody();
}

class _V12sPrivateRequestBody extends LorinPrivateRequestBody {
  @override
  LorinCmdBase get cmdBase => V12sCmd();

  @override
  int get defaultTargetDevice => TargetDeviceType.eucHmic.rawValue;
}
